using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.ComponentModel.Composition.Primitives;
using System.Linq;

using Caliburn.Micro;

using Haushaltsbuch.Events;
using Haushaltsbuch.Extensions;
using Haushaltsbuch.ViewModels;
using Haushaltsbuch.ViewModels.Interfaces;

using Ninject;

namespace Haushaltsbuch
{
    public class AppBootstrapper : Bootstrapper<IShell>
    {
        private IKernel kernel;

        /// <summary>
        ///     By default, we are configured to use MEF
        /// </summary>
        protected override void Configure()
        {
            this.ConfigureExceptionHandling();
            this.kernel = new StandardKernel();

            this.kernel.Bind<IWindowManager>().To<WindowManager>();
            this.kernel.Bind<IEventAggregator>().To<EventAggregator>().InSingletonScope();

            var assemblies = this.SelectAssemblies().ToArray();

            this.kernel.BindExports(a => a.From(assemblies));

            //ActionMessageExtensions.AddActionPermissionHandling(this.container.GetExportedValue<IEventAggregator>());
            ActionMessageExtensions.AddActionPermissionHandling(this.kernel.Get<IEventAggregator>());

        }

        private void ConfigureExceptionHandling()
        {
            Coroutine.Completed += (o, e) => { if (e.Error != null) this.HandleException(e.Error); };
            Application.Dispatcher.UnhandledException += (o, e) => this.HandleException(e.Exception);
        }

        private void HandleException(Exception error)
        {
            var shell = IoC.Get<IShell>();
            shell.DisplayFatalException(error);
        }

        protected override object GetInstance(Type serviceType, string key)
        {
            if (!string.IsNullOrEmpty(key)) throw new ArgumentNullException("Ninject hat kein Key");

            var result = this.kernel.TryGet(serviceType);
            if (result != null)
                return result;

            throw new Exception(string.Format("Could not locate any instances of contract {0}.", serviceType));
        }

        protected override IEnumerable<object> GetAllInstances(Type serviceType)
        {
            return this.kernel.GetAll(serviceType);
        }

        protected override void BuildUp(object instance)
        {
            this.kernel.Inject(instance);
        }
    }
}